﻿using System;
using System.Collections.Generic;
using WMPLib;
using Zipun.VkOnlineMusic.Api;
using Zipun.VkOnlineMusic.Api.Domain;

namespace Zipun.VkOnlineMusic.Logic
{
    public class Player
    {
        private readonly WindowsMediaPlayer _wmp;
        private VkAudio _nowPlaying;
        private readonly Random _random;

        public event EventHandler<PlayStateChangedEventArgs> PlayStateChanged;
        public event EventHandler<EventArgs> NowPlayingChanged;

        public PlayState PlayState
        {
            get
            {
                switch (_wmp.playState)
                {
                    case WMPPlayState.wmppsPlaying:
                        return PlayState.Playing;
                    case WMPPlayState.wmppsPaused:
                        return PlayState.Paused;
                    case WMPPlayState.wmppsStopped:
                        return PlayState.Stopped;
                    default:
                        return PlayState.None;
                }
            }
        }

        public VkToken VkToken { get; private set; }

        public List<VkAudio> Audios { get; set; }

        public VkAudio NowPlaying
        {
            get { return _nowPlaying; }
            private set
            {
                _nowPlaying = value;
                if (NowPlayingChanged != null)
                    NowPlayingChanged.Invoke(this, new EventArgs());
            }
        }

        public bool Shuffle { get; set; }

        public Player()
        {
            _wmp = new WindowsMediaPlayer();
            _wmp.PlayStateChange += WmpOnPlayStateChange;
            _random = new Random();
        }

        private void WmpOnPlayStateChange(int newState)
        {
            if (PlayStateChanged != null)
                PlayStateChanged.Invoke(null, new PlayStateChangedEventArgs(newState));
            switch (newState)
            {
                case (int)WMPPlayState.wmppsReady:
                    _wmp.controls.play();
                    break;
                case (int)WMPPlayState.wmppsMediaEnded:
                    {
                        GotoNext();
                    }
                    break;
            }
        }

        public void Initialize(VkToken vkToken)
        {
            VkToken = vkToken;
            var audioManager = new AudioManager(VkToken);
            Audios = audioManager.GetList();
        }

        public void Initialize(PlayerMode mode)
        {
            var audioManager = new AudioManager(VkToken);
            switch (mode)
            {
                case PlayerMode.MyAudio:
                    Audios = audioManager.GetList();
                    break;
                    case PlayerMode.Suggestions:
                    Audios = audioManager.GetSuggestions();
                    break;
            }
        }

        public void Pause()
        {
            _wmp.controls.pause();
        }

        public void Play()
        {
            _wmp.controls.play();
        }
        public void Play(VkAudio audio)
        {
            NowPlaying = audio;
            _wmp.URL = NowPlaying.Url;
            Play();
        }

        public void Stop()
        {
            _wmp.controls.stop();
        }

        public void GotoNext()
        {
            if (!Audios.Contains(NowPlaying))
            {
                if (Audios.Count > 0)
                    Play(Audios[0]);
                return;
            }
            // Select next track
            var nextPayingIndex = getNextIndex();
            Play(Audios[nextPayingIndex]);
        }

        private int getNextIndex()
        {
            var index = Audios.IndexOf(NowPlaying);
            int nextIndex = index;
            if (Shuffle)
                nextIndex = _random.Next(Audios.Count - 1);
            if (nextIndex == index)
            {
                nextIndex = index + 1;
                if (nextIndex >= Audios.Count)
                    nextIndex = 0;
            }
            return nextIndex;
        }

        public void GotoPrevious()
        {
            if (!Audios.Contains(NowPlaying))
            {
                if (Audios.Count > 0)
                    Play(Audios[0]);
                return;
            }
            // Select previous track
            var payingIndex = Audios.IndexOf(NowPlaying) - 1;
            if (payingIndex < 0)
                payingIndex = Audios.Count - 1;
            Play(Audios[payingIndex]);
        }

        public void AddAudio(VkAudio vkAudio)
        {
            var audioManager = new AudioManager(VkToken);
            audioManager.Add(vkAudio.Id, vkAudio.OwnerId);
        }

        public bool DeleteAudio(VkAudio vkAudio)
        {
            var audioManager = new AudioManager(VkToken);
            return audioManager.Delete(vkAudio.Id, vkAudio.OwnerId);
        }
    }
}